package com.xyht.sca_s.student_manage_system.modules.payment.wxpay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.entity.SmsWnsChargePaymentCategoryDivide;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.entity.SmsWnsChargePaymentRecord;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.mapper.SmsWnsChargePaymentCategoryDivideMapper;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.mapper.SmsWnsChargePaymentRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.entity.SmsEnrollmentManagementStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.mapper.SmsEnrollmentManagementStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.entity.CallbackAESResourceEntity;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.entity.CallbackBodyEntity;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.entity.CallbackPayResourceEntity;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.entity.WxPayConfigProperties;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.service.WxService;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.util.AESUtil;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.util.WxPayUtil;
import com.xyht.sca_s.student_manage_system.modules.rxRegistrationAdvance.entity.RxRegistrationAdvanceStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.rxRegistrationAdvance.mapper.RxRegistrationAdvanceStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.rxRegistrationChargePayment.entity.RxRegistrationChargePaymentCategoryDivide;
import com.xyht.sca_s.student_manage_system.modules.rxRegistrationChargePayment.entity.RxRegistrationChargePaymentRecord;
import com.xyht.sca_s.student_manage_system.modules.rxRegistrationChargePayment.mapper.RxRegistrationChargePaymentCategoryDivideMapper;
import com.xyht.sca_s.student_manage_system.modules.rxRegistrationChargePayment.mapper.RxRegistrationChargePaymentRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.trainingSchool.entity.SmsTsTrainingInfo;
import com.xyht.sca_s.student_manage_system.modules.trainingSchool.mapper.SmsTsTrainingInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.user.util.SMSUtil;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsChargePlanStudentStatus;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsRegistrationProcessDetail;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsChargePlanStudentStatusMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsRegistrationProcessDetailMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.modules.chargePayment.constant.SmsWnsChargePaymentRecordConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.enrollmentManagement.constant.AdvanceChargeStatusConstant.ADVANCE_CHARGE_STATUS_SUCCESS;
import static com.xyht.sca_s.student_manage_system.modules.rxRegistrationAdvance.constant.RegistrationStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.rxRegistrationChargePayment.constant.PaymentTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.RegistrationProcessDetailConstant.*;


@Service
@Slf4j
public class WxServiceImpl implements WxService {
    @Resource
    private PlatformTransactionManager transactionManager; // 事务
    @Resource
    private WxPayUtil wxPayUtil;
    @Resource
    private AESUtil aesUtil;
    @Resource
    private SmsWnsChargePaymentRecordMapper smsWnsChargePaymentRecordMapper;
    @Resource
    private SmsEnrollmentManagementStudentInfoMapper smsEnrollmentManagementStudentInfoMapper;
    @Resource
    private SmsWnsChargePaymentCategoryDivideMapper smsWnsChargePaymentCategoryDivideMapper;
    @Resource
    private SmsWnsChargePlanStudentStatusMapper smsWnsChargePlanStudentStatusMapper;
    @Resource
    private SmsWnsRegistrationProcessDetailMapper smsWnsRegistrationProcessDetailMapper;
    @Resource
    private WxPayConfigProperties wxPayConfigProperties;
    @Resource
    private RxRegistrationChargePaymentRecordMapper rxRegistrationChargePaymentRecordMapper;
    @Resource
    private RxRegistrationAdvanceStudentInfoMapper rxRegistrationAdvanceStudentInfoMapper;
    @Resource
    private RxRegistrationChargePaymentCategoryDivideMapper rxRegistrationChargePaymentCategoryDivideMapper;
    @Resource
    private SmsTsTrainingInfoMapper smsTsTrainingInfoMapper;

    @Override
    public String wxPayCallback(CallbackBodyEntity entity, HttpServletRequest request, HttpServletResponse response) {
        log.info("-------------------------------支付回调进来------------------------");
        log.info("entity:{}", JSON.toJSONString(entity));

//        CallbackBodyResourceEntity body = new CallbackBodyResourceEntity();
//        BeanUtils.copyProperties(entity, body);
//        RequestParam requestParam = new RequestParam.Builder()
//                .signType(SIGN_TYPE)
//                .serialNumber(request.getParameter("Wechatpay-Serial"))
//                .signature(request.getParameter("Wechatpay-Signature"))
//                .timestamp(request.getParameter("Wechatpay-Timestamp"))
//                .nonce(request.getParameter("Wechatpay-Nonce"))
//                .body(JSONObject.toJSONString(body))
//                .build();
//        log.info("requestParam:{}", JSON.toJSONString(requestParam));
//        CallbackPayResourceEntity resourceEntity = wxPayUtil.checkNotificationSign(requestParam);
//        log.info("resourceEntity:{}", JSON.toJSONString(resourceEntity));

        CallbackPayResourceEntity resourceEntity = new CallbackPayResourceEntity();
        try {
            CallbackAESResourceEntity aesResourceEntity = entity.getResource();
            String resource = aesUtil.decryptToString(aesResourceEntity.getAssociated_data().getBytes(),
                    aesResourceEntity.getNonce().getBytes(),
                    aesResourceEntity.getCiphertext(),
                    wxPayConfigProperties.getConfigs().get(0).getWX_API_V3_KEY());
            log.debug("resource++++++++++++++++" + resource);
            resourceEntity = JSONObject.parseObject(resource, CallbackPayResourceEntity.class);
            if (resourceEntity == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dealWithPayment(resourceEntity, response);
    }

    public String dealWithPayment(CallbackPayResourceEntity resourceEntity, HttpServletResponse response) {
        // 开启事务
        DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
        // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
        dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        // 设置嵌套事务
        TransactionStatus status = transactionManager.getTransaction(dt);
        try {
            if (resourceEntity.getTrade_state().equals("SUCCESS")) {
                SmsWnsChargePaymentRecord paymentRecord = smsWnsChargePaymentRecordMapper.selectById(resourceEntity.getOut_trade_no());
                if (paymentRecord == null) {
                    return successResp(response);
                }

                if (paymentRecord.getPaymentAmount() != null) {
                    return successResp(response);
                }

                paymentRecord.setPaymentTransactionId(resourceEntity.getTransaction_id());
                BigDecimal paymentAmount = centsToYuan(resourceEntity.getAmount().getTotal());
                paymentRecord.setPaymentAmount(paymentAmount); // 支付金额
                Date paymentTime = TimeUtil.rfc3339ParseDate(resourceEntity.getSuccess_time());
                paymentRecord.setPaymentTime(paymentTime); // 支付时间
                smsWnsChargePaymentRecordMapper.updateById(paymentRecord);

                //0.新生缴费 1.普通缴费 2.招生预支付  各功能的独立逻辑
                if (paymentRecord.getType() == CHARGE_PAYMENT_RECORD_TYPE_NEW_STUDENT || paymentRecord.getType() == CHARGE_PAYMENT_RECORD_TYPE_COMMON) {
                    List<SmsWnsChargePaymentCategoryDivide> categoryDivideList = smsWnsChargePaymentCategoryDivideMapper.selectList(new LambdaQueryWrapper<SmsWnsChargePaymentCategoryDivide>()
                            .eq(SmsWnsChargePaymentCategoryDivide::getPaymentRecordId, paymentRecord.getId()));
                    for (SmsWnsChargePaymentCategoryDivide categoryDivide : categoryDivideList) {
                        categoryDivide.setPaymentAmount(categoryDivide.getAmount());
                        categoryDivide.setPaymentTime(paymentTime);

                        SmsWnsChargePlanStudentStatus studentStatus = smsWnsChargePlanStudentStatusMapper.selectOne(new LambdaQueryWrapper<SmsWnsChargePlanStudentStatus>()
                                .eq(SmsWnsChargePlanStudentStatus::getPlanId, categoryDivide.getPlanId())
                                .eq(SmsWnsChargePlanStudentStatus::getUserId, categoryDivide.getUserId())
                                .eq(SmsWnsChargePlanStudentStatus::getChargeItemId, categoryDivide.getChargeItemId()));
                        // 本项欠费金额 = 本项欠费金额 - 本项实缴金额
                        BigDecimal needPayAmount = studentStatus.getNeedPaymentAmount().subtract(categoryDivide.getAmount());

                        // 修改学生缴费状态
                        if (needPayAmount.compareTo(BigDecimal.valueOf(0)) <= 0) { // 欠费金额<=0
                            studentStatus.setIsPaid(true); // 已缴清
                        }
                        studentStatus.setNeedPaymentAmount(needPayAmount);
                        // 本项实缴金额 = 本项分到的支付金额 + 原金额
                        studentStatus.setPaymentAmount(categoryDivide.getPaymentAmount().add(studentStatus.getPaymentAmount() == null ? BigDecimal.valueOf(0) : studentStatus.getPaymentAmount()));
                        studentStatus.setPaymentTime(paymentTime);
                        smsWnsChargePlanStudentStatusMapper.updateById(studentStatus);

                        // 修改金额分配
                        categoryDivide.setNeedPayAmount(needPayAmount);
                        smsWnsChargePaymentCategoryDivideMapper.updateById(categoryDivide);
                    }

                    // 新生缴费设置新生该流程为进行中
                    if (paymentRecord.getType() == CHARGE_PAYMENT_RECORD_TYPE_NEW_STUDENT) {
                        List<SmsWnsRegistrationProcessDetail> detailList = smsWnsRegistrationProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsWnsRegistrationProcessDetail>()
                                .eq(SmsWnsRegistrationProcessDetail::getUserId, paymentRecord.getUserId())
                                .eq(SmsWnsRegistrationProcessDetail::getSort, REGISTRATION_PROCESS_DETAIL_SORT_TWO) // 财务处报道
                                .eq(SmsWnsRegistrationProcessDetail::getStatus, REGISTRATION_PROCESS_DETAIL_STATUS_NOT_START) // 未开始
                                .orderByDesc(SmsWnsRegistrationProcessDetail::getCreateTime));
                        if (!detailList.isEmpty()) {
                            SmsWnsRegistrationProcessDetail detail = detailList.get(0);
                            detail.setStatus(REGISTRATION_PROCESS_DETAIL_STATUS_START); // 设置为进行中
                            smsWnsRegistrationProcessDetailMapper.updateById(detail);
                        }
                    }
                } else if (paymentRecord.getType() == CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY) {
                    SmsEnrollmentManagementStudentInfo updateEnrollmentStudent = new SmsEnrollmentManagementStudentInfo();
                    updateEnrollmentStudent.setId(paymentRecord.getEventId());
                    updateEnrollmentStudent.setAdvanceChargeTime(paymentTime);
                    updateEnrollmentStudent.setAdvanceChargeMoney(paymentAmount);
                    updateEnrollmentStudent.setAdvanceChargeStatus(ADVANCE_CHARGE_STATUS_SUCCESS);

                    smsEnrollmentManagementStudentInfoMapper.updateById(updateEnrollmentStudent);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            // 手动回滚事务
            transactionManager.rollback(status);
        } finally {
            if (status.isNewTransaction() && !status.isCompleted()) {
                transactionManager.commit(status);
            }
        }
        log.info("-------------------------------支付回调结束------------------------");
        return successResp(response);
    }

    @Override
    public String wxPayCallbackOne(CallbackBodyEntity entity, HttpServletRequest request, HttpServletResponse response) {
        log.info("-------------------------------支付回调进来------------------------");
        log.info("entity:{}", JSON.toJSONString(entity));

//        CallbackBodyResourceEntity body = new CallbackBodyResourceEntity();
//        BeanUtils.copyProperties(entity, body);
//        RequestParam requestParam = new RequestParam.Builder()
//                .signType(SIGN_TYPE)
//                .serialNumber(request.getParameter("Wechatpay-Serial"))
//                .signature(request.getParameter("Wechatpay-Signature"))
//                .timestamp(request.getParameter("Wechatpay-Timestamp"))
//                .nonce(request.getParameter("Wechatpay-Nonce"))
//                .body(JSONObject.toJSONString(body))
//                .build();
//        log.info("requestParam:{}", JSON.toJSONString(requestParam));
//        CallbackPayResourceEntity resourceEntity = wxPayUtil.checkNotificationSign(requestParam);
//        log.info("resourceEntity:{}", JSON.toJSONString(resourceEntity));

        CallbackPayResourceEntity resourceEntity = new CallbackPayResourceEntity();
        try {
            CallbackAESResourceEntity aesResourceEntity = entity.getResource();
            String resource = aesUtil.decryptToString(aesResourceEntity.getAssociated_data().getBytes(),
                    aesResourceEntity.getNonce().getBytes(),
                    aesResourceEntity.getCiphertext(),
                    wxPayConfigProperties.getConfigs().get(0).getWX_API_V3_KEY());
            log.debug("resource++++++++++++++++" + resource);
            resourceEntity = JSONObject.parseObject(resource, CallbackPayResourceEntity.class);
            if (resourceEntity == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dealWithPayment(resourceEntity, response);
    }

    @Override
    public String wxPayCallbackTwo(CallbackBodyEntity entity, HttpServletRequest request, HttpServletResponse response) {
        log.info("-------------------------------支付回调进来------------------------");
        log.info("entity:{}", JSON.toJSONString(entity));

//        CallbackBodyResourceEntity body = new CallbackBodyResourceEntity();
//        BeanUtils.copyProperties(entity, body);
//        RequestParam requestParam = new RequestParam.Builder()
//                .signType(SIGN_TYPE)
//                .serialNumber(request.getParameter("Wechatpay-Serial"))
//                .signature(request.getParameter("Wechatpay-Signature"))
//                .timestamp(request.getParameter("Wechatpay-Timestamp"))
//                .nonce(request.getParameter("Wechatpay-Nonce"))
//                .body(JSONObject.toJSONString(body))
//                .build();
//        log.info("requestParam:{}", JSON.toJSONString(requestParam));
//        CallbackPayResourceEntity resourceEntity = wxPayUtil.checkNotificationSign(requestParam);
//        log.info("resourceEntity:{}", JSON.toJSONString(resourceEntity));

        CallbackPayResourceEntity resourceEntity = new CallbackPayResourceEntity();
        try {
            CallbackAESResourceEntity aesResourceEntity = entity.getResource();
            String resource = aesUtil.decryptToString(aesResourceEntity.getAssociated_data().getBytes(),
                    aesResourceEntity.getNonce().getBytes(),
                    aesResourceEntity.getCiphertext(),
                    wxPayConfigProperties.getConfigs().get(1).getWX_API_V3_KEY());
            log.debug("resource++++++++++++++++" + resource);
            resourceEntity = JSONObject.parseObject(resource, CallbackPayResourceEntity.class);
            if (resourceEntity == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dealWithPayment(resourceEntity, response);
    }

    @Override
    public String rxRegistrationPayCallback(CallbackBodyEntity entity, HttpServletRequest request, HttpServletResponse response) {
        log.info("-------------------------------支付回调进来------------------------");
        log.info("entity:{}", JSON.toJSONString(entity));

        CallbackPayResourceEntity resourceEntity = new CallbackPayResourceEntity();
        try {
            CallbackAESResourceEntity aesResourceEntity = entity.getResource();
            String resource = aesUtil.decryptToString(aesResourceEntity.getAssociated_data().getBytes(),
                    aesResourceEntity.getNonce().getBytes(),
                    aesResourceEntity.getCiphertext(),
                    wxPayConfigProperties.getConfigs().get(0).getWX_API_V3_KEY());
            log.debug("resource++++++++++++++++" + resource);
            resourceEntity = JSONObject.parseObject(resource, CallbackPayResourceEntity.class);
            if (resourceEntity == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 开启事务
        DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
        // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
        dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        // 设置嵌套事务
        TransactionStatus status = transactionManager.getTransaction(dt);
        try {
            if (resourceEntity.getTrade_state().equals("SUCCESS")) {
                RxRegistrationChargePaymentRecord paymentRecord = rxRegistrationChargePaymentRecordMapper.selectById(resourceEntity.getOut_trade_no());
                if (paymentRecord == null) {
                    return successResp(response);
                }

                if (paymentRecord.getPaymentAmount() != null) {
                    return successResp(response);
                }

                paymentRecord.setPaymentTransactionId(resourceEntity.getTransaction_id());
                BigDecimal paymentAmount = centsToYuan(resourceEntity.getAmount().getTotal());
                paymentRecord.setPaymentAmount(paymentAmount); // 支付金额
                Date paymentTime = TimeUtil.rfc3339ParseDate(resourceEntity.getSuccess_time());
                paymentRecord.setPaymentTime(paymentTime); // 支付时间
                rxRegistrationChargePaymentRecordMapper.updateById(paymentRecord);

                // 修改分配数据
                RxRegistrationChargePaymentCategoryDivide divide = new RxRegistrationChargePaymentCategoryDivide();
                divide.setPaymentTime(paymentTime);
                rxRegistrationChargePaymentCategoryDivideMapper.update(divide, new LambdaQueryWrapper<RxRegistrationChargePaymentCategoryDivide>()
                            .eq(RxRegistrationChargePaymentCategoryDivide::getPaymentRecordId, paymentRecord.getId()));
                String type = paymentRecord.getType();

                //设置录取通知书序列号 D240001 这里只需要设置0001即可
                //获取当前年份后两位
                Date date = new Date(); // 假设这是2024年的某个日期
                SimpleDateFormat sdf = new SimpleDateFormat("yy");
                String yearLastTwo = sdf.format(date);
                int admissionNumber = 1;
                //通过录取通知书序列号排名
                List<RxRegistrationAdvanceStudentInfo> studentInfoList = rxRegistrationAdvanceStudentInfoMapper.selectList(new LambdaQueryWrapper<RxRegistrationAdvanceStudentInfo>()
                        .isNotNull(RxRegistrationAdvanceStudentInfo::getAdmissionNumber)
                        .orderByDesc(RxRegistrationAdvanceStudentInfo::getAdmissionNumber));
                if (studentInfoList != null && studentInfoList.size() > 0) {
                    admissionNumber = studentInfoList.get(0).getAdmissionNumber();
                    String existYearLastTwo = String.valueOf(admissionNumber).substring(0, 2);
                    if (!existYearLastTwo.equals(yearLastTwo)) {
                        // 当年份变化时，直接使用新年的序列号
                        admissionNumber = Integer.parseInt(yearLastTwo + "0001");
                    } else {
                        // 当年份相同时，仅递增序列号
                        // 提取序列号部分，并加1
                        admissionNumber += 1;
                    }
                } else {//第一个人缴费时 生成240001
                    admissionNumber = Integer.parseInt(yearLastTwo + "0001");
                }

                //招生预报名: advance, 确认报名: confirm,迎新报到: welcome  各功能的独立逻辑
                switch (type) {
                    case RX_REGISTRATION_CHARGE_PAYMENT_RECORD_TYPE_ADVANCE: {
                        RxRegistrationAdvanceStudentInfo rxRegistrationAdvanceStudentInfo = new RxRegistrationAdvanceStudentInfo();
                        rxRegistrationAdvanceStudentInfo.setId(paymentRecord.getStuId());
                        rxRegistrationAdvanceStudentInfo.setAdmissionNumber(admissionNumber);
                        rxRegistrationAdvanceStudentInfo.setAdvanceStatus(REGISTRATION_STATUS_FINISH);
                        rxRegistrationAdvanceStudentInfoMapper.updateById(rxRegistrationAdvanceStudentInfo);

                        //发送录取通知短信
                        RxRegistrationAdvanceStudentInfo studentInfo = rxRegistrationAdvanceStudentInfoMapper.selectById(paymentRecord.getStuId());
                        SMSUtil.SendAdmission(studentInfo.getTel(), studentInfo.getName());
                        break;
                    }
                    case RX_REGISTRATION_CHARGE_PAYMENT_RECORD_TYPE_CONFIRM: {

                        RxRegistrationAdvanceStudentInfo studentInfo = rxRegistrationAdvanceStudentInfoMapper.selectById(paymentRecord.getStuId());
                        //第一阶段未完成时 生成序列号
                        if (studentInfo.getAdvanceStatus() != REGISTRATION_STATUS_FINISH) {
                            studentInfo.setAdmissionNumber(admissionNumber);
                        }
                        studentInfo.setAdvanceStatus(REGISTRATION_STATUS_FINISH);
                        studentInfo.setConfirmStatus(REGISTRATION_STATUS_FINISH);
                        rxRegistrationAdvanceStudentInfoMapper.updateById(studentInfo);
                        break;
                    }
                    case RX_REGISTRATION_CHARGE_PAYMENT_RECORD_TYPE_WELCOME: {
                        RxRegistrationAdvanceStudentInfo rxRegistrationAdvanceStudentInfo = new RxRegistrationAdvanceStudentInfo();
                        rxRegistrationAdvanceStudentInfo.setId(paymentRecord.getStuId());
                        rxRegistrationAdvanceStudentInfo.setAdvanceStatus(REGISTRATION_STATUS_FINISH);
                        rxRegistrationAdvanceStudentInfo.setConfirmStatus(REGISTRATION_STATUS_FINISH);
                        rxRegistrationAdvanceStudentInfo.setWelcomeStatus(REGISTRATION_STATUS_FINISH);
                        rxRegistrationAdvanceStudentInfoMapper.updateById(rxRegistrationAdvanceStudentInfo);
                        break;
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            // 手动回滚事务
            transactionManager.rollback(status);
        } finally {
            if (status.isNewTransaction() && !status.isCompleted()) {
                transactionManager.commit(status);
            }
        }
        return successResp(response);
    }

    @Override
    public String tsPayCallback(CallbackBodyEntity entity, HttpServletRequest request, HttpServletResponse response) {
        log.info("---------------------------培训学校支付回调进来------------------------");
        log.info("entity:{}", JSON.toJSONString(entity));

        CallbackPayResourceEntity resourceEntity = new CallbackPayResourceEntity();
        try {
            CallbackAESResourceEntity aesResourceEntity = entity.getResource();
            String resource = aesUtil.decryptToString(aesResourceEntity.getAssociated_data().getBytes(),
                    aesResourceEntity.getNonce().getBytes(),
                    aesResourceEntity.getCiphertext(),
                    wxPayConfigProperties.getConfigs().get(0).getWX_API_V3_KEY());
            log.debug("resource++++++++++++++++" + resource);
            resourceEntity = JSONObject.parseObject(resource, CallbackPayResourceEntity.class);
            if (resourceEntity == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 开启事务
        DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
        // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
        dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        // 设置嵌套事务
        TransactionStatus status = transactionManager.getTransaction(dt);
        try {
            if (resourceEntity.getTrade_state().equals("SUCCESS")) {
                RxRegistrationChargePaymentRecord paymentRecord = rxRegistrationChargePaymentRecordMapper.selectById(resourceEntity.getOut_trade_no());
                if (paymentRecord == null) {
                    return successResp(response);
                }

                if (paymentRecord.getPaymentAmount() != null) {
                    return successResp(response);
                }

                paymentRecord.setPaymentTransactionId(resourceEntity.getTransaction_id());
                BigDecimal paymentAmount = centsToYuan(resourceEntity.getAmount().getTotal());
                paymentRecord.setPaymentAmount(paymentAmount); // 支付金额
                Date paymentTime = TimeUtil.rfc3339ParseDate(resourceEntity.getSuccess_time());
                paymentRecord.setPaymentTime(paymentTime); // 支付时间
                rxRegistrationChargePaymentRecordMapper.updateById(paymentRecord);

                SmsTsTrainingInfo trainingInfo = smsTsTrainingInfoMapper.selectById(paymentRecord.getPlanId());
                if (trainingInfo != null) {
                    trainingInfo.setPayAmount(paymentAmount);
                    trainingInfo.setIsPaid(true);
                    smsTsTrainingInfoMapper.updateById(trainingInfo);
                }

                // 修改分配数据
                List<RxRegistrationChargePaymentCategoryDivide> divideList = rxRegistrationChargePaymentCategoryDivideMapper.selectList(new LambdaQueryWrapper<RxRegistrationChargePaymentCategoryDivide>()
                        .eq(RxRegistrationChargePaymentCategoryDivide::getPaymentRecordId, paymentRecord.getId()));
                if (!divideList.isEmpty()) {
                    RxRegistrationChargePaymentCategoryDivide divide = new RxRegistrationChargePaymentCategoryDivide();
                    divide.setPaymentTime(paymentTime);

                    List<String> idList = divideList.stream().map(RxRegistrationChargePaymentCategoryDivide::getId).collect(Collectors.toList());
                    rxRegistrationChargePaymentCategoryDivideMapper.update(divide, new LambdaQueryWrapper<RxRegistrationChargePaymentCategoryDivide>()
                            .in(RxRegistrationChargePaymentCategoryDivide::getId, idList));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 手动回滚事务
            transactionManager.rollback(status);
        } finally {
            if (status.isNewTransaction() && !status.isCompleted()) {
                transactionManager.commit(status);
            }
        }
        return successResp(response);
    }

    /**
     * 将以分为单位的金额(Integer)转换为以元为单位的金额(BigDecimal)
     *
     * @param moneyInCents 以分为单位的金额(Integer)
     * @return 以元为单位的金额(BigDecimal)
     */
    private BigDecimal centsToYuan(Integer moneyInCents) {
        // 将分转换为元, 需要除以100, 并将结果存储为BigDecimal类型
        return new BigDecimal(moneyInCents).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
    }

    /**
     * 失败应答
     */
    private String failResp(HttpServletResponse response) {
        response.setStatus(500);
        Map<String, String> map = new HashMap<>();
        map.put("code", "FAIL");
        map.put("message", "失败");
        return JSON.toJSONString(map);
    }

    /**
     * 成功应答
     */
    private String successResp(HttpServletResponse response) {
        response.setStatus(200);
        Map<String, String> map = new HashMap<>();
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        return JSON.toJSONString(map);
    }

    /**
     * 手动回滚事务
     *
     * @param status 嵌套事务
     */
    private void rollback(TransactionStatus status) {
        // 手动回滚事务
        transactionManager.rollback(status);
        if (status.isNewTransaction() && !status.isCompleted()) {
            transactionManager.commit(status);
        }
    }
}
